home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
System Booster
/
System Booster.iso
/
Archives
/
Drivers
/
vc_2_2.lha
/
ParNet
/
Source
/
unit_str.c
< prev
Wrap
C/C++ Source or Header
|
1994-11-01
|
4KB
|
201 lines
/*
** $Header: SRC:CVSROOT/Vector/ParNet/unit_str.c,v 1.1.1.1 1994/06/23 02:39:43 Barnard Exp $
*/
/*
** This code was originally written by Matthew Dillon and put into Public Domain
**
** All changes concerning the adaption of Matt's original code to the
** Vector Connection I/O board are © 1991-1994 by Henning Schmiedehausen
** All rights for this changes are reserved. The original code is Public Domain
**
** This code is distributed with the expressed written permission of Matthew
** Dillon (Thank you very much, Matt)
**
*/
/*
* UNIT_STR.C STREAM PROTOCOL (not impl yet)
*
* currently just datagram proto.
*/
#include "defs.h"
#include "unit_str_protos.h"
#include "unit_ctl_protos.h"
#include "parnet_protos.h"
#include "task_protos.h"
#include <proto/exec.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include "parnet_asm.h"
void StreamBeginIO();
void StreamAbortIO();
void StreamClose();
void StreamData();
/*
* Called under Forbid
*/
void
UnitStreamOpen(iob, unitnum, flags)
Iob *iob;
long unitnum;
long flags;
{
Unit *unit;
if (unit = FindUnitForPort(iob->io_Port)) {
if (unit->BeginIO != StreamBeginIO) {
iob->io_Error = PPERR_PORT_IN_USE;
return;
}
} else {
unit = AllocUnit(iob, StreamBeginIO, StreamAbortIO, StreamData, StreamClose);
}
iob->io_Unit = unit;
++unit->RefCnt;
}
void
StreamClose(iob)
Iob *iob;
{
Unit *unit = iob->io_Unit;
if (--unit->RefCnt == 0) {
FreeUnit(unit);
}
iob->io_Unit = NULL;
}
/*
* UnitStreamData() is called whenever a low level network operation
* completes for the given unit. cmd is:
*
* 'r' received data packet
* 'w' wrote data packet
* 'W' timeout writing data packet
*
* The routine is called with the unit locked.
*/
void
StreamData(cmd, packet, actual)
Packet *packet;
long actual; /* 'w', 'W' */
{
Unit *unit = packet->io_Unit;
Iob *iob;
long n;
switch(cmd) {
case 'r':
if (iob = (Iob *)RemHead(&unit->PendIOR)) {
iob->io_Flags &= ~IOF_QUEUED;
n = actual;
iob->io_Actual = actual;
if (n < 0)
n = 0;
if (n > iob->io_Length) {
n = iob->io_Length;
iob->io_Error = PPERR_WARN_OVFLOW;
}
movmem((char *)packet->Data1, (char *)iob->io_Data, n);
if ((iob->io_Flags & IOF_QUICK) == 0)
ReplyMsg(&iob->io_Message);
}
/*
* Note that if no read requests are pending the datagram is
* thrown away.
*/
FreeParPacket(packet);
break;
case 'W':
Remove(packet->iob);
iob->io_Flags &= ~IOF_QUEUED;
iob->io_Error = 1;
iob->io_Actual = actual;
if ((iob->io_Flags & IOF_QUICK) == 0)
ReplyMsg(&iob->io_Message);
FreeParPacket(packet);
break;
case 'w':
Remove(packet->iob);
iob->io_Flags &= ~IOF_QUEUED;
iob->io_Actual = actual;
if ((iob->io_Flags & IOF_QUICK) == 0)
ReplyMsg(&iob->io_Message);
FreeParPacket(packet);
break;
}
}
void
StreamBeginIO(iob)
Iob *iob;
{
Unit *unit = iob->io_Unit;
Packet *packet;
iob->io_Error = 0;
iob->io_Actual = 0;
iob->io_Message.mn_Node.ln_Type = NT_MESSAGE;
switch(iob->io_Command) {
case CMD_READ:
LockAddr(unit->UnitLock);
iob->io_Flags &= ~IOF_QUICK;
iob->io_Flags |= IOF_QUEUED;
AddTail(&unit->PendIOR, iob);
UnlockAddr(unit->UnitLock);
return;
case CMD_WRITE:
packet = AllocParPacket(iob, unit, iob->io_Data, iob->io_Length, NULL, 0);
LockAddr(unit->UnitLock);
AddTail(&unit->PendIOW, iob);
UnlockAddr(unit->UnitLock);
QueuePacketForWrite(packet);
return;
default:
CtlBeginIO(iob);
return;
}
}
/*
* Abort a read or write request. Currently only read requests may be
* aborted.
*/
void
StreamAbortIO(iob)
Iob *iob;
{
if (iob->io_Command == CMD_READ) {
LockAddr(iob->io_Unit->UnitLock);
if ((iob->io_Flags & (IOF_QUEUED|IOF_RUN)) == IOF_QUEUED) {
Remove(iob);
UnlockAddr(iob->io_Unit->UnitLock);
iob->io_Flags &= ~IOF_QUEUED;
iob->io_Error = -1; /* ??? */
ReplyMsg(&iob->io_Message);
} else {
UnlockAddr(iob->io_Unit->UnitLock);
}
}
}